import random

def apx_prob_atleast(prob_list, n, trials=100):
    """ Aproximate the probability of at least n events happening,
    given a list of probabilities of events
    """
    success = 0
    for i in range(trials):
        result = 0
        for p in prob_list:
            if p < random.random():
                result += 1
        if result >= n:
            success += 1
    return float(success) / float(trials)


def mean(l):
    """ mean value of a list """
    return sum(l) / float(len(l))

def rem(l, x):
    """ build a new list with the first 'x' removed """
    new_l = []
    for i, e in enumerate(l):
        if e == x:
            new_l += l[i + 1:]
            break
        else:
            new_l.append(e)
            
    return new_l


class Player:
    
    def hunt_choices(self, round_number, current_food, current_reputation, m,
                player_reputations):
        # Do some brainless decisions in the first rounds
        if round_number == 0:
            return ['h'] * len(player_reputations)
        elif round_number == 1:
            return ['s'] * len(player_reputations)
        
        # If it's a heads up round -> slack your way out
        if len(player_reputations) == 1:
            return ['s']
        
        choices = []
        
        # mean reputaion of the population -> used for various heuristic decisions
        mean_reputation = sum([current_reputation] + player_reputations) / (len(player_reputations) + 1)
        
        # a list of all probabilities for every hunt
        all_probs = [current_reputation] * len(player_reputations)
        for rep in player_reputations:
            all_probs += [rep] * len(player_reputations)

        # compute an aproximative probability of 'm' happening
        m_probability = apx_prob_atleast(all_probs, m)
        
        for rep in player_reputations:
            # slacker/hunter protection
            if rep <= .1 or rep >= .9:
                choices.append('s')
                continue
            # if the reputaion of the population is higher than 'm' => slack
            if mean_reputation > m_probability \
               and rep < mean_reputation:
                choices.append('s')
                continue
            
            # if the probability of 'm' is hign => slack
            if m_probability >= .7:
                choices.append('s')
                continue
            
            # don't be a pushover!
            if current_reputation > .7:
                choices.append('s')
                continue
            
            # compute some complicated utilities
            
            # compute some probabilities, excluding my reputaion and the current opponent reputation
            known_probs = rem(rem(all_probs, current_reputation), rep)
            
            # gain = opponent_reputation * (outcome + common_goods_probability * 2) +
            # + (1 - opponent_reputation) * (outcome + common_goods_probability * 2) -
            # - action_cost
            
            gain_hunt = rep * (6 + apx_prob_atleast(known_probs, m - 2) * 2) + \
                (1 - rep) * (3 + apx_prob_atleast(known_probs, m - 1) * 2) - 6
            gain_slack = rep * (3 + apx_prob_atleast(known_probs, m - 1) * 2) + \
                (1 - rep) * (0 + apx_prob_atleast(known_probs, m - 2) * 2) - 2
            
            s = gain_hunt + gain_slack
            gain_hunt /= s + 0.0001
            gain_slack /= s + 0.0001
            
            if random.random() < gain_hunt:
                choices.append('h')
                continue
            else:
                choices.append('s')
                continue
        
        return choices
                
    
    def hunt_outcomes(self, food_earnings):
        pass # do nothing
    
    def round_end(self, award, m, number_hunters):
        pass # do nothing  
    